use axum::{http::StatusCode, response::IntoResponse, routing, Json, Router};
use base64::{engine::general_purpose::STANDARD, Engine as _};
use openssl::{hash::MessageDigest, rsa::Padding, sign::Signer};
use serde_json::json;
use tracing::{debug, info};

use crate::vo::{self, LicenseRequestForm};

pub struct LicenseController {
    routes: Router,
}

impl Into<Router> for LicenseController {
    fn into(self) -> Router {
        self.routes
    }
}

impl LicenseController {
    pub fn init() -> Self {
        let routes = Router::new().route("/license", routing::post(issue_license));

        Self { routes }
    }
}

async fn issue_license(Json(request_form): Json<LicenseRequestForm>) -> impl IntoResponse {
    info!(request_form = ?request_form, "Received license request");
    let mut license = vo::License::new(
        request_form.licensee_name,
        request_form.assignee_name,
        request_form.assignee_email,
    );
    for p in request_form.request_products.into_iter() {
        license.add_product(p, request_form.valid_days);
    }
    let serialized_license = license.serialize();
    debug!(license = ?license, "License created: {}", serialized_license);

    let private_key = crate::certificate::get_private_key();
    let mut signer = Signer::new(MessageDigest::sha1(), private_key).unwrap();
    signer.set_rsa_padding(Padding::PKCS1).unwrap();
    signer.update(serialized_license.as_bytes()).unwrap();

    let cert = crate::certificate::get_public_key().to_der().unwrap();

    let base64_license = STANDARD.encode(serialized_license);
    let base64_signature = STANDARD.encode(signer.sign_to_vec().unwrap());
    let base64_cert = STANDARD.encode(cert);

    let license_response = format!(
        "{}-{}-{}-{}",
        license.license_id, base64_license, base64_signature, base64_cert
    );

    (StatusCode::OK, Json(json!({"license": license_response})))
}
